(function () {
  'use strict';
  var drawVisual;
  var concertHallBuffer;
  var WIDTH, HEIGHT;
  var audioCtx;
  var canvasCtx;
  var analyser, gainNode;
  var duration = 0;
  var audioWave = null;
  var soundSource = null;
  var sectionEnded = false;
  var btnSection = null;
  var btnAll = null;
  var time = null;
  var lineOneLeft = 0;
  var lineTwoLeft = 0;
  var timeLine = null;
  var disabled = true
  function init(boxId) {
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    if (audioCtx) {
      analyser = audioCtx.createAnalyser();
      analyser.minDecibels = -90;
      analyser.maxDecibels = -10;
      analyser.smoothingTimeConstant = 0.85;
      gainNode = audioCtx.createGain();
      initHtml(boxId)
      var canvas = document.getElementById('canvas');
      if (canvas) {
        canvasCtx = canvas.getContext("2d");
        WIDTH = canvas.width;
        HEIGHT = canvas.height - 20;
      }
    }
  }
  function initHtml(boxId) {
    var box = document.getElementById(boxId)
    box.innerHTML = "<div class='vocal-print'>" +
      "<div id='vocalHandle'></div>" +
      "<div id='vocalLine'></div>" +
      "<div id='vocalHandle2'></div>" +
      "<div id='vocalLine2'></div>" +
      "<div id='vocalRange'></div>" +
      "<div id='timeLine'></div>" +
      "<canvas id='canvas' width='650' height='120'></canvas>" +
      "<div id='vocalTool'><span class='btn' id='btnSection'>播放区间</span></div>" +
      "</div>"
    var x = 0;
    var y = 0;
    var l = 0;
    var t = 0;
    var isDown = false;
    // var begin = 0;
    // var end = 0;
    var target = null;
    var handle = document.getElementById('vocalHandle')
    var line = document.getElementById('vocalLine')
    var handleTwo = document.getElementById('vocalHandle2')
    var lineTwo = document.getElementById('vocalLine2')
    var range = document.getElementById('vocalRange')
    timeLine = document.getElementById('timeLine')
    btnSection = document.getElementById('btnSection')
    
    // btnAll = document.getElementById('btnAll')
    btnSection.onclick = function () {
      if (disabled) {
        return;
      }
      var v = audioWave.duration() * 1000 / WIDTH // 计算1毫秒等于多宽
      //计算每16.8ms偏移量 (width/(width*v/16.8))
      var offset = Math.abs(lineTwoLeft - lineOneLeft) / (Math.abs(lineTwoLeft - lineOneLeft) * v / (1000 / 60));
      if (btnSection.isPlay) {//暂停
        if (audioCtx.state === 'running') {
          cancelAnimationFrame(drawVisual)
          sectionEnded = false
          audioCtx.suspend()
        }
      } else {//播放
        if (audioCtx.state === 'suspended' && !sectionEnded) {//继续播放
          move()
          audioCtx.resume()
        } else {//重新播放
          timeLine.style.display = "block"
          timeLine.style.left = (lineTwoLeft > lineOneLeft ? lineOneLeft : lineTwoLeft) + 25 + 'px'
          move()
          audioWave.play((lineTwoLeft > lineOneLeft ? lineOneLeft : lineTwoLeft) * v / 1000, Math.abs(lineTwoLeft - lineOneLeft) * v / 1000)
        }
      }
      btnSection.isPlay = !btnSection.isPlay
      btnSection.innerText = btnSection.isPlay ? '暂停播放' : '继续播放'
      function move() {
        drawVisual = requestAnimationFrame(move);
        var left = parseFloat(timeLine.style.left)
        timeLine.style.left = left + offset + 'px'
      }
    }
    // handle.onselectstart = function () { 
    //   return false; 
    // }
    handle.onmousedown = mousedown
    window.onmousemove = mousemove
    handle.onmouseup = mouseup
    window.onmouseup = mouseup
    handleTwo.onmousedown = mousedown
    handleTwo.onmouseup = mouseup
    range.onmousedown = mousedown
    range.onmouseup = mouseup
    function mousedown(e) {
      //获取x坐标和y坐标
      x = e.clientX;
      y = e.clientY;
      //获取左部和顶部的偏移量
      target = e.target;
      l = e.target.offsetLeft;
      t = e.target.offsetTop;
      //开关打开
      isDown = true;
      //设置样式  
      // dv.style.cursor = 'move';
      // begin = parseInt(line.style.left) - 25 || 0;
    }
    function mousemove(e) {
      if (isDown == false) {
        return;
      }
      //获取x和y
      var nx = e.clientX;
      var ny = e.clientY;
      //计算移动后的左偏移量和顶部的偏移量
      var nl = nx - (x - l);
      var nt = ny - (y - t);
      if (nl >= 17 && nl <= WIDTH + 18) {
        if (target.id === 'vocalHandle2') {
          handleTwo.style.left = nl + 'px';
          lineTwo.style.left = nl + 8 + 'px';
        } else if (target.id === 'vocalHandle') {
          handle.style.left = nl + 'px';
          line.style.left = nl + 8 + 'px';
        } else {
          var width = parseInt(range.style.width)
          if (nl <= WIDTH - width + 20) {
            range.style.left = nl + 8 + 'px';
            handleTwo.style.left = nl + 'px';
            lineTwo.style.left = nl + 8 + 'px';
            handle.style.left = nl + width + 'px';
            line.style.left = nl + width + 8 + 'px';
            lineTwoLeft = parseInt(lineTwo.style.left) - 25 || 0;
            lineOneLeft = parseInt(line.style.left) - 25 || 0;
          }
        }
        if (target.id !== 'vocalRange') {
          lineTwoLeft = parseInt(lineTwo.style.left) - 25 || 0;
          lineOneLeft = parseInt(line.style.left) - 25 || 0;
          range.style.left = (lineTwoLeft > lineOneLeft ? lineOneLeft : lineTwoLeft) + 25 + 'px'
          range.style.width = Math.abs(lineTwoLeft - lineOneLeft) + 'px'
        }
      }
    }
    function mouseup(e) {
      //开关关闭
      isDown = false;
      // if (target.id === 'vocalHandle2') {
      //   lineTwoLeft = parseInt(lineTwo.style.left) - 25 || 0;
      // } else {
      //   lineOneLeft = parseInt(line.style.left) - 25 || 0;
      // }
      // console.log(`lineOneLeft=${lineOneLeft},lineTwoLeft=${lineTwoLeft}`)
      // var lineOneLeft = parseInt(line.style.left) - 25 || 0;
      // var lineTwoLeft = parseInt(lineTwo.style.left) - 25 || 0;
      // end = parseInt(line.style.left) - 25 || 0;
      // if (begin > end) {
      //   let temp = end
      //   end = begin
      //   begin = temp
      // }
      // range.style.left = begin + 25 + 'px'
      // range.style.width = end - begin + 'px'
      // if (target && (target.id === 'vocalRange' || target.id === 'vocalHandle2' || target.id === 'vocalHandle')) {
      //   if (audioWave) {
      //     var v = audioWave.duration() * 1000 / WIDTH
      //     audioWave.play((lineTwoLeft > lineOneLeft ? lineOneLeft : lineTwoLeft) * v / 1000, Math.abs(lineTwoLeft - lineOneLeft) * v / 1000)
      //   }
      // }
      // target = null
      // event.stopPropagation()
      // if (audioWave) {
      //   var v = audioWave.duration() * 1000 / WIDTH
      //   audioWave.play((lineTwoLeft > lineOneLeft ? lineOneLeft : lineTwoLeft) * v / 1000, Math.abs(lineTwoLeft - lineOneLeft) * v / 1000)
      // }
    }

  }
  function decodeAudioData(arraybuffer) {
    audioCtx.decodeAudioData(arraybuffer, function (buffer) {
      var soundSource = audioCtx.createBufferSource();
      soundSource.connect(gainNode);
      gainNode.connect(analyser)
      analyser.connect(audioCtx.destination)
      soundSource.buffer = buffer
      concertHallBuffer = buffer;
      soundSource.start()
      duration = buffer.duration
      soundSource.onended = function () {
        cancelAnimationFrame(drawVisual)
        if (btnSection) {
          disabled = false;
          btnSection.style.cursor = 'pointer';
        }
      }
      visualize(buffer.duration)
      scale(buffer.duration)
    })
  }
  function visualize(duration) {
    analyser.fftSize = 256;
    var bufferLength = analyser.fftSize;
    var dataArray = new Uint8Array(bufferLength);

    canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
    var x = 0;
    var draw = function () {

      drawVisual = requestAnimationFrame(draw);

      analyser.getByteTimeDomainData(dataArray);

      canvasCtx.fillStyle = 'rgb(200, 200, 200)';
      // this.canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);

      canvasCtx.lineWidth = 0.5;
      canvasCtx.strokeStyle = 'rgb(141, 141, 141)';

      canvasCtx.beginPath();

      var sliceWidth = WIDTH * 1.0 / (bufferLength * (duration * 1000 / 16.7));
      // var x = 0;
      for (var i = 0; i < bufferLength; i++) {

        var v = dataArray[i] / 128.0;
        var y = v * HEIGHT / 2;

        if (i === 0) {
          canvasCtx.moveTo(x, y);
        } else {
          canvasCtx.lineTo(x, y);
        }

        x += sliceWidth;
      }
      canvasCtx.stroke();
    };

    draw();
  }
  function scale(duration) {
    let height = HEIGHT + 20
    let length = duration * 10
    let v = WIDTH / (duration * 10)
    canvasCtx.lineWidth = 0.6;
    canvasCtx.font = "12px";
    let str = duration.toFixed(1) + '秒'
    canvasCtx.fillText(str, WIDTH - 40, 15)
    canvasCtx.strokeStyle = 'rgb(141, 141, 141)';
    canvasCtx.moveTo(0, height);
    canvasCtx.lineTo(WIDTH, height);
    let j = 0
    for (let i = 0; i < length; i++) {
      canvasCtx.moveTo(i * v, height - 1);
      if (i % 10 === 0) {
        canvasCtx.fillText(j + 's', i * v - 5, height - 16)
        canvasCtx.lineTo(i * v, height - 14);
        j += 1
      } else if (i % 5 === 0) {
        canvasCtx.lineTo(i * v, height - 10);
      } else {
        canvasCtx.lineTo(i * v, height - 6);
      }
    }
    canvasCtx.stroke();
  }
  var Audiowave = function (boxId) {
    init(boxId)
    audioWave = this;
  }
  Audiowave.prototype = {
    duration() {
      return duration
    },
    loadAudio(url) {
      var self = this
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.withCredentials = false;
      xhr.responseType = 'arraybuffer';
      xhr.onload = function () {
        var code = (xhr.status + '')[0];
        if (code !== '0' && code !== '2' && code !== '3') {
          return;
        }
        decodeAudioData(xhr.response);
      }
      xhr.send()
    },
    play(offset, duration) {
      if (soundSource) {
        soundSource.disconnect(0)
        soundSource = null
      }
      soundSource = audioCtx.createBufferSource()
      soundSource.buffer = concertHallBuffer
      soundSource.onended = function () {
        sectionEnded = true
        if (btnSection) {
          cancelAnimationFrame(drawVisual)
          timeLine.style.left = (lineTwoLeft > lineOneLeft ? lineTwoLeft : lineOneLeft) + 25 + 'px'
          btnSection.isPlay = false;
          btnSection.innerText = '播放区间';
        }
      }
      soundSource.connect(gainNode);
      gainNode.connect(analyser)
      soundSource.start(0, offset, duration)
    }
  }
  // Add support for AMD (Asynchronous Module Definition) libraries such as require.js.
  if (typeof define === 'function' && define.amd) {
    define([], function () {
      return {
        Audiowave: Audiowave
      };
    });
  }

  // Add support for CommonJS libraries such as browserify.
  if (typeof exports !== 'undefined') {
    exports.Audiowave = Audiowave;
  }

  // Define globally in case AMD is not available or unused.
  if (typeof window !== 'undefined') {
    window.Audiowave = Audiowave;
  } else if (typeof global !== 'undefined') { // Add to global in Node.js (for testing, etc).
    global.Audiowave = Audiowave;
  }
})()